package com.shuai.chatroom.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.shuai.chatroom.common.AppConstant;
import com.shuai.chatroom.config.UserOnLineStateManager;
import com.shuai.chatroom.entity.MessageInfo;
import com.shuai.chatroom.entity.UserInfo;
import com.shuai.chatroom.entity.vo.FriendInfoVO;
import com.shuai.chatroom.entity.vo.MessageInfoVO;
import com.shuai.chatroom.service.MessageService;
import com.shuai.chatroom.service.SessionsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;

@Component
public class WebSocketController extends TextWebSocketHandler {

    @Autowired
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private UserOnLineStateManager userOnLineStateManager;

    @Autowired
    private SessionsService sessionsService;

    @Autowired
    private MessageService messageService;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("链接建立成功！");
        UserInfo userInfo = (UserInfo) session.getAttributes().get(AppConstant.USER_SESSION_KEY);
        if (userInfo == null || userInfo.getUId() == null) {
            return;
        }
        //将用户的登录状态设置为上线，添加到userSessions哈希表中
        userOnLineStateManager.upLine(userInfo.getUId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //1.解析用前端发送的消息内容
        System.out.println("接收到了消息" + message.toString());
        String payload = message.getPayload();
        MessageInfo messageInfo = objectMapper.readValue(payload, MessageInfo.class);   //将消息内容通过JackSon转换成一个消息对象
        if (messageInfo.getSessionId() == null || messageInfo.getMessContent() == null) {
            return;
        }
        UserInfo userInfo = (UserInfo) session.getAttributes().get(AppConstant.USER_SESSION_KEY);
        System.out.println("发送消息的用户：" + userInfo);
        if (userInfo == null || userInfo.getUId() == null) {
            return;
        }
        messageInfo.setFromUId(userInfo.getUId());

        //根据会话id从数据库中查询所有在该会话中的用户信息，拿到用户id
        //循环遍历这些用户id，获取对应的WebSocketSession信息
        //如果当前的用户不在线，则直接将消息插入到message表中，否则推送消息后再插入。同时也要给发送消息的客户端推送一份自己发送的消息用户展示
        transferMessage(userInfo, messageInfo);
    }

    /**
     * 完成消息的保存和转发
     */
    private void transferMessage(UserInfo userInfo, MessageInfo messageInfo) throws IOException {
        //根据会话id从数据库中查询所有在该会话中的用户信息，拿到用户id
        List<FriendInfoVO> friendsList = sessionsService.getFriendsList(messageInfo.getSessionId(), userInfo.getUId());
        //把发送消息的用户自己也给加入到响应列表中
        FriendInfoVO myself = new FriendInfoVO();
        myself.setFId(userInfo.getUId());
        myself.setFriendName(userInfo.getUsername());
        myself.setFriendPhoto(userInfo.getPhoto());
        myself.setFriendNickname(userInfo.getNickname());
        myself.setSessionId(messageInfo.getSessionId());
        friendsList.add(myself);
        //构建消息响应对象
        MessageInfoVO messageInfoVO = new MessageInfoVO();
        messageInfoVO.setSessionId(messageInfo.getSessionId());
        messageInfoVO.setNickname(userInfo.getNickname());
        messageInfoVO.setFromUId(userInfo.getUId());
        messageInfoVO.setCreateTime(LocalDateTime.now());
        messageInfoVO.setMessContent(messageInfo.getMessContent());
        messageInfoVO.setUsername(userInfo.getUsername());
        messageInfoVO.setFriendPhoto(userInfo.getPhoto());
        //循环遍历这些用户id，获取对应的WebSocketSession信息
        //如果当前的用户不在线，则直接将消息插入到message表中，否则推送消息后再插入。同时也要给发送消息的客户端推送一份自己发送的消息用户展示
        for (FriendInfoVO friendInfoVO : friendsList) {
            WebSocketSession userWebSocketSession = userOnLineStateManager.getUserSession(friendInfoVO.getFId());
            if (userWebSocketSession == null) {
                //用户不在线,什么也不做
                continue;
            }
            //将消息推送给用户
            userWebSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(messageInfoVO)));
            //将消息存储到数据库中，即使用户不在线，那他在下次登录时也会查询到这些待接收的消息
        }
        messageInfo.setIsRead(0);   //这里统一设置消息类型为未读
        messageService.addMessage(messageInfo);
        //更新会话的时间
        sessionsService.updateTime(messageInfo.getSessionId());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("连接出现异常!");
        UserInfo userInfo = (UserInfo) session.getAttributes().get(AppConstant.USER_SESSION_KEY);
        if (userInfo == null || userInfo.getUId() == null) {
            return;
        }
        userOnLineStateManager.offLine(userInfo.getUId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("连接关闭！");
        UserInfo userInfo = (UserInfo) session.getAttributes().get(AppConstant.USER_SESSION_KEY);
        if (userInfo == null || userInfo.getUId() == null) {
            return;
        }
        userOnLineStateManager.offLine(userInfo.getUId(), session);
    }
}
